package com.xsf.jieyou.business.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.baidu.aip.util.Base64Util;
import com.xsf.jieyou.business.common.dto.ResponseResult;
import com.xsf.jieyou.business.common.dto.ResponseStatus;
import com.xsf.jieyou.business.dto.LoginParam;
import com.xsf.jieyou.business.service.LoginServiceImpl;
import com.xsf.jieyou.business.utils.BaiduAiUtil;
import com.xsf.jieyou.provider.api.ProviderTbUserService;
import com.xsf.jieyou.provider.domain.TbUser;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;

/**
 * (百度AI)人脸识别  控制器
 *
 * @author xsfno1
 * @version v1.0.0
 * @date 2020/3/11 4:29
 * @see com.xsf.jieyou.business.controller
 **/
@RestController
@RequestMapping("/user/faceai")
public class FaceController {
    @Resource
    private BaiduAiUtil baiduAiUtil;
    @Resource
    private LoginServiceImpl loginServiceImpl;
    @Reference(version = "1.0.0")
    private ProviderTbUserService providerTbUserService;
    @Value("${alicloud.oss.endpoint}")
    private String endpoint;
    @Value("${alicloud.accessKeyId}")
    private String accessKeyId;
    @Value("${alicloud.accessKeySecret}")
    private String accessKeySecret;
    @Value("${alicloud.oss.bucketName}")
    private String bucketName;
    @Value("${alicloud.oss.folder}")
    private String folder;


    /**
     * 人脸登录：根据落地页随机拍摄的面部头像进行登录
     * 根据拍摄的图片调用百度云AI进行检索查找
     * 扫描二维码之后，使用拍摄照片进行登录
     * 返回值：登录成功之后返回的用户id
     * 登录失败：null
     *
     * @param attachment {@link MultipartFile} 照片
     */
    @PostMapping("/unauth/login")
    public ResponseResult loginByFace(@RequestParam(name = "file") MultipartFile attachment) throws Exception {
        //人脸登录获取用户id（不为null登录成功）
        //1.调用百度云AI查询当前的用户
        String userId = this.baiduAiUtil.faceSearch(Base64Util.encode(attachment.getBytes()));
        //2.自动登录（token）,执行oAuth2安全认证
        // 人脸识别成功 , 自动登录
        if (userId != null) {
            //1.查询用户对象
            TbUser tbUser = this.providerTbUserService.get(Long.parseLong(userId));
            //2.oAuth2安全认证
            if (tbUser != null) {
                //无密码登录方式,通过设置默认密码"12345678"完成登录认证
                return this.loginServiceImpl.login(new LoginParam("#" + tbUser.getUsername(), "12345678"));
            }
        }
        return new ResponseResult<>(ResponseStatus.DEFEATED);
    }

    /**
     * 图像检测，判断图片中是否存在面部头像,同时只能存在1人头像
     */
    @PostMapping("/unauth/checkface")
    public ResponseResult checkFace(@RequestParam(name = "file") MultipartFile attachment) throws Exception {
        String image = Base64Util.encode(attachment.getBytes());
        return this.baiduAiUtil.faceCheck(image) ?
                new ResponseResult(ResponseStatus.SUCCESS) :
                new ResponseResult(ResponseStatus.DEFEATED);
    }

    @PostMapping("/updateface")
    public ResponseResult updateFace(@RequestParam(name = "file") MultipartFile attachment) {
        try {
            // 图片
            String image = Base64Util.encode(attachment.getBytes());

            // 1.检测人脸
            Boolean isFace = this.baiduAiUtil.faceCheck(image);
            if (!isFace) {
                return new ResponseResult<>(ResponseStatus.DEFEATED.code(), "未检测到人脸");
            }
            // 2.userid
            String username = this.getAuthenticationName();
            System.out.println("username:" + username);
            TbUser tbUser = this.providerTbUserService.get(username);
            System.out.println("tbUser:" + tbUser);
            String userid = tbUser.getId() + "";
            // 3.将头像插入阿里云OSS并保存URL到数据库中
            String imgName = folder + "/" + userid + ".jpg";
            System.out.println("userid:" + userid);
            OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            client.putObject(new PutObjectRequest(bucketName, imgName, multipartFileToFile(attachment)));
            //https://xsf-bucket.oss-cn-beijing.aliyuncs.com/JieYou/gem.jpg
            String imgUrl = "//" + bucketName + "." + endpoint + "/" + imgName;
            System.out.println("imgUrl:" + imgUrl);
            tbUser.setFaceIcon(imgUrl);
            this.providerTbUserService.update(tbUser);
            // 4.更新人脸
            //判断是否存在人脸库
            Boolean isExist = this.baiduAiUtil.faceExist(userid);
            Boolean flag = isExist ? this.baiduAiUtil.faceUpdate(userid, image) :
                    this.baiduAiUtil.faceRegister(userid, image);
            return flag ?
                    new ResponseResult(ResponseStatus.SUCCESS) :
                    new ResponseResult(ResponseStatus.DEFEATED);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ResponseResult(ResponseStatus.DEFEATED);
    }

    /**
     * 获取 oAuth2 认证用户名
     *
     * @return 认证用户名
     */
    private String getAuthenticationName() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // "#"是无密码方式登录标记
        return authentication.getName().startsWith("#") ?
                authentication.getName().substring(1) :
                authentication.getName();
    }

    /**
     * MultipartFile 2 File
     *
     * @param file {@link MultipartFile}
     */
    public static File multipartFileToFile(MultipartFile file) throws Exception {
        File toFile = null;
        if (file.getSize() != 0) {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(Objects.requireNonNull(file.getOriginalFilename()));

            try {
                OutputStream os = new FileOutputStream(toFile);
                int bytesRead = 0;
                byte[] buffer = new byte[8192];
                while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

            ins.close();
        }
        return toFile;
    }
}
